#pragma  once 
#include "../server.hpp"
#include <fstream>
#include <sys/stat.h>
#include <regex>
#define DEFAULT_TIMEOUT 5

std::unordered_map<int,std::string> _statu_msg = 
{
    {100,  "Continue"},
    {101,  "Switching Protocol"},
    {102,  "Processing"},
    {103,  "Early Hints"},
    {200,  "OK"},
    {201,  "Created"},
    {202,  "Accepted"},
    {203,  "Non-Authoritative Information"},
    {204,  "No Content"},
    {205,  "Reset Content"},
    {206,  "Partial Content"},
    {207,  "Multi-Status"},
    {208,  "Already Reported"},
    {226,  "IM Used"},
    {300,  "Multiple Choice"},
    {301,  "Moved Permanently"},
    {302,  "Found"},
    {303,  "See Other"},
    {304,  "Not Modified"},
    {305,  "Use Proxy"},
    {306,  "unused"},
    {307,  "Temporary Redirect"},
    {308,  "Permanent Redirect"},
    {400,  "Bad Request"},
    {401,  "Unauthorized"},
    {402,  "Payment Required"},
    {403,  "Forbidden"},
    {404,  "Not Found"},
    {405,  "Method Not Allowed"},
    {406,  "Not Acceptable"},
    {407,  "Proxy Authentication Required"},
    {408,  "Request Timeout"},
    {409,  "Conflict"},
    {410,  "Gone"},
    {411,  "Length Required"},
    {412,  "Precondition Failed"},
    {413,  "Payload Too Large"},
    {414,  "URI Too Long"},
    {415,  "Unsupported Media Type"},
    {416,  "Range Not Satisfiable"},
    {417,  "Expectation Failed"},
    {418,  "I'm a teapot"},
    {421,  "Misdirected Request"},
    {422,  "Unprocessable Entity"},
    {423,  "Locked"},
    {424,  "Failed Dependency"},
    {425,  "Too Early"},
    {426,  "Upgrade Required"},
    {428,  "Precondition Required"},
    {429,  "Too Many Requests"},
    {431,  "Request Header Fields Too Large"},
    {451,  "Unavailable For Legal Reasons"},
    {501,  "Not Implemented"},
    {502,  "Bad Gateway"},
    {503,  "Service Unavailable"},
    {504,  "Gateway Timeout"},
    {505,  "HTTP Version Not Supported"},
    {506,  "Variant Also Negotiates"},
    {507,  "Insufficient Storage"},
    {508,  "Loop Detected"},
    {510,  "Not Extended"},
    {511,  "Network Authentication Required"}
};

std::unordered_map<std::string,std::string> _mime_msg = 
{
    {".aac",        "audio/aac"},
    {".abw",        "application/x-abiword"},
    {".arc",        "application/x-freearc"},
    {".avi",        "video/x-msvideo"},
    {".azw",        "application/vnd.amazon.ebook"},
    {".bin",        "application/octet-stream"},
    {".bmp",        "image/bmp"},
    {".bz",         "application/x-bzip"},
    {".bz2",        "application/x-bzip2"},
    {".csh",        "application/x-csh"},
    {".css",        "text/css"},
    {".csv",        "text/csv"},
    {".doc",        "application/msword"},
    {".docx",       "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
    {".eot",        "application/vnd.ms-fontobject"},
    {".epub",       "application/epub+zip"},
    {".gif",        "image/gif"},
    {".htm",        "text/html"},
    {".html",       "text/html"},
    {".ico",        "image/vnd.microsoft.icon"},
    {".ics",        "text/calendar"},
    {".jar",        "application/java-archive"},
    {".jpeg",       "image/jpeg"},
    {".jpg",        "image/jpeg"},
    {".js",         "text/javascript"},
    {".json",       "application/json"},
    {".jsonld",     "application/ld+json"},
    {".mid",        "audio/midi"},
    {".midi",       "audio/x-midi"},
    {".mjs",        "text/javascript"},
    {".mp3",        "audio/mpeg"},
    {".mpeg",       "video/mpeg"},
    {".mpkg",       "application/vnd.apple.installer+xml"},
    {".odp",        "application/vnd.oasis.opendocument.presentation"},
    {".ods",        "application/vnd.oasis.opendocument.spreadsheet"},
    {".odt",        "application/vnd.oasis.opendocument.text"},
    {".oga",        "audio/ogg"},
    {".ogv",        "video/ogg"},
    {".ogx",        "application/ogg"},
    {".otf",        "font/otf"},
    {".png",        "image/png"},
    {".pdf",        "application/pdf"},
    {".ppt",        "application/vnd.ms-powerpoint"},
    {".pptx",       "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
    {".rar",        "application/x-rar-compressed"},
    {".rtf",        "application/rtf"},
    {".sh",         "application/x-sh"},
    {".svg",        "image/svg+xml"},
    {".swf",        "application/x-shockwave-flash"},
    {".tar",        "application/x-tar"},
    {".tif",        "image/tiff"},
    {".tiff",       "image/tiff"},
    {".ttf",        "font/ttf"},
    {".txt",        "text/plain"},
    {".vsd",        "application/vnd.visio"},
    {".wav",        "audio/wav"},
    {".weba",       "audio/webm"},
    {".webm",       "video/webm"},
    {".webp",       "image/webp"},
    {".woff",       "font/woff"},
    {".woff2",      "font/woff2"},
    {".xhtml",      "application/xhtml+xml"},
    {".xls",        "application/vnd.ms-excel"},
    {".xlsx",       "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
    {".xml",        "application/xml"},
    {".xul",        "application/vnd.mozilla.xul+xml"},
    {".zip",        "application/zip"},
    {".3gp",        "video/3gpp"},
    {".3g2",        "video/3gpp2"},
    {".7z",         "application/x-7z-compressed"}
};


namespace  wyl
{
  class Util
  {
  private: 
    //16进制转换10进制
    static char HEXOTOI(char c)
    {
      if(c >= '0' && c <= '9') return c - '0'; 
      if(c >= 'a' && c <= 'z') return c - 'a' + 10; 
      if(c >= 'A' && c <= 'Z')return c - 'A' + 10; 
      return -1;
    }
  public:

    static size_t split(const std::string str , const std::string sep , std::vector<std::string>* arr)
    {
      size_t offset = 0;
      while(offset < str.size())
      {
        size_t pos = str.find(sep,offset);
        if(pos == std::string::npos)
        {
          //没有找到，如果是在结尾，直接返回
          if(pos == str.size()) break; 
          //把末尾字符加上
          arr->push_back(str.substr(offset));
          return arr->size();
        }
        //找到了，从 offset ~ pos - offset 
        if(pos != offset) arr->push_back(str.substr(offset,pos-offset));
        offset = pos + sep.size();
      }
      return arr->size();
    }

    //读取文件内容
    
    static bool ReadFile(const std::string filename,std::string* buf)   
    {
       std::ifstream ifs(filename,std::ios::binary); 
       if(!ifs.is_open())
       {
         ELOG("Open %s Failed!",filename.c_str());
         return false; 
       }
       size_t fsize = 0; 
       ifs.seekg(0,ifs.end);//跳转到文件末尾 
       fsize = ifs.tellg(); //获取当前位置到初始位置的大小 
       ifs.seekg(ifs.beg) ; //回到初始位置 
       buf->resize(fsize);
       ifs.read(&(*buf)[0],fsize); //把文件读到字符串str   
       if(!ifs.good())
       {
         ELOG("READ %s FAILED",filename.c_str());
         ifs.close();
         return false;
       }
       ifs.close();
       return true; 
    }

    //写入文件内容
    static bool WriteFile(const std::string& filename,const std::string& buf)
    {
      //打开文件，没有则创建
      std::ofstream os(filename,std::ios::binary | std::ios::trunc); 
      if(!os.is_open())
      {
        ELOG("FILE %s OPEN FAILED",filename.c_str());
        return false; 
      }
      os.write(buf.c_str(),buf.size());
      if(!os.good())
      {
        ELOG("FILE %s WRITE FAILED!",filename.c_str());
        os.close();
        return false; 
      }
      os.close();
      return true;
    }
    

    //Url编码
    static std::string UrlEcode(const std::string& url , bool convert_space_to_plus)
    {
      std::string res ; 
      for(auto& c : url)
      {
        if(c == '.' || c == '-' || c == '~' || c == '_' || isalnum(c))
        {
          res += c; 
          continue; 
        }
        if(c == ' ' && convert_space_to_plus)
        {
          res += '+';
          continue; 
        }
        //编码 
        char tmp[4] ;
        snprintf(tmp,4,"%%%02X",c);
        res += tmp; 
      }
      return res;
    }
    
    //Url解码
    static std::string UrlDcode(const std::string& url,bool convert_space_to_plus)
    {
      std::string res; 
      for(int i = 0 ; i < url.size() ; i++)
      {
        if(url[i] == '+' && convert_space_to_plus) 
        {
          res += ' ';
          continue; 
        }
        if(url[i] == '%')
        {
          char v1 = HEXOTOI(url[i+1]); 
          char v2 = HEXOTOI(url[i+2]); 
          char v3 = v1*16 + v2 ;
          res += v3; 
          i+=2 ;
          continue; 
        }
        res += url[i];
      }
      return res;
    }

    //获取响应状态码描述信息
    static std::string StatuDesc(int statu_code)
    {
      auto it = _statu_msg.find(statu_code);
      if(it == _statu_msg.end())
      {
        return "UNKNOW";
      }
      return it->second;
    }

    //根据文件后缀名提取文件mime
    static std::string ExtMine(const std::string& filename)
    {
      size_t pos = filename.find_last_of('.'); 
      if(pos == std::string::npos) 
      {
        return "application/octet-stream"; 
      }
      std::string Ext = filename.substr(pos);
      auto it = _mime_msg.find(Ext);
      if(it == _mime_msg.end())
      {
        return "application/octet-stream"; 
      }
      return it->second;
    }

    //文件是否是一个目录 
    static bool IsDirectory(const std::string& filename)
    {
      struct stat st; 
      int ret = stat(filename.c_str(),&st);
      if(ret < 0) return false; 
      return S_ISDIR(st.st_mode);
    }

    //判断文件是否是一个普通文件
    static bool IsRegular(const std::string& filename)
    {
      struct stat st;
      int ret = stat(filename.c_str(),&st); 
      if(ret < 0) return false; 
      return S_ISREG(st.st_mode);
    }

    //判断http请求是否有效
    static bool ValidPath(const std::string& requestpath)
    {
      std::vector<std::string> arr;  
      split(requestpath,"/",&arr);
      int level = 0 ;
      for(auto& s : arr)
      {
        if(s == "..")
        {
          level--; 
          if(level < 0) return false; 
          continue; 
        }
        level++; 
      }
      return true;
    }
  };


  class HttpRequest
  {
  public:
      std::string _method; //请求方法
      std::string _path;   //资源路劲
      std::string _version;//协议版本
      std::string _body;   //请求正文
      std::smatch _matches;//正则提取的资源路径数据
      std::unordered_map<std::string,std::string> _headers; //头部字段 key val结构
      std::unordered_map<std::string,std::string> _params; //查询字符串

  public:
      HttpRequest() :_version("HTTP/1.1") {}
      //重置
      void Reset()
      {
        _method.clear();
        _path.clear();
        _version = "HTTP/1.1";
        _body.clear(); 
        std::smatch matches; 
        _matches.swap(matches);
        _headers.clear();
        _params.clear();
      }

      //插入一条请求报头
      void SetHeader(const std::string& key , const std::string& val)
      {
        _headers.insert(std::make_pair(key,val));
      }

      //判断是否存在指定的头部字段
      bool HasHeader(const std::string& key) const 
      {
        auto it = _headers.find(key);
        if(it == _headers.end()) return false;
        return true; 
      }

      //获取头部字段对应的val值 
      std::string GetHeader(const std::string& key) const 
      {
        auto it = _headers.find(key);
        if(it == _headers.end()) return ""; 
        return it->second;
      }

      //插入查询字符串
      void SetParam(const std::string& key , const std::string& val)
      {
        _headers.insert(std::make_pair(key,val));
      }

      //判断是否有查询字符串
      bool HasParam(const std::string& key)const 
      {
        auto it = _headers.find(key);
        if(it == _headers.end()) return false;
        return true; 
      }
      
      //获取指定查询字符串的值
      std::string GetParam(const std::string& key) const 
      {
        auto it = _headers.find(key);
        if(it == _headers.end()) return ""; 
        return it->second;
      }

      //获取正文长度
      size_t ContentLength() const 
      {
        bool ret = HasHeader("Content-Length"); 
        if(!ret) return 0; 
        return std::stol(GetHeader("Content-Length"));
      }

      bool Close() const  
      {
        if(HasHeader("Connection") && GetHeader("Connection") == "keep-alive") 
        {
          return false; 
        }
        return true;
      }
  };
  

  class HttpResponse
  {
    public:
      int _statu; //响应状态码 
      bool _redirect_flag; //是否重定向 
      std::string _body; //响应正文
      std::string _redirect_url ;// 重定向的url
      std::unordered_map<std::string,std::string> _headers; 

    public:
      HttpResponse(int statu) : _statu(statu){}
      void Reset()
      {
        _statu = 200;
        _redirect_flag = false; 
        _body.clear();
        _redirect_url.clear();
        _headers.clear();
      }
      void SetHeader(const std::string& key ,const std::string val)
      {
        _headers.insert(std::make_pair(key,val));
      }
      bool HasHeader(const std::string& key)
      {
        auto it = _headers.find(key);
        if(it == _headers.end()) return false;
        return true; 
      }
      std::string GetHeader(const std::string& key)
      {
        auto it = _headers.find(key);
        if(it == _headers.end()) return "";
        return it->second;
      }
      void SetContext(const std::string& body ,const std::string& type )
      {
        _body = body;
        SetHeader("Content-Type",type);
      }
      void SetRedirect(std::string& url , int statu = 302)
      {
        _redirect_flag = true; 
        _statu = statu; 
        _redirect_url = url ;
      }
      bool Close()
      {
        if(HasHeader("Connection") && GetHeader("Connection") == "keep-alive") return false;
        return true;
      }
  };


  typedef enum 
  {
    RECV_HTTP_ERROR, 
    RECV_HTTP_LINE,
    RECV_HTTP_HEAD,
    RECV_HTTP_BODY,
    RECV_HTTP_OVER
  }HttpRecvStatu;



  class HttpContext
  {
#define MAX_LINE 8196
  private:
    int _resp_staut; //响应状态码
    HttpRecvStatu _recv_statu; //当前接收及解析时的状态
    HttpRequest _request;//已经解析得到的请求信息
  public:
    bool RecvHttpLine(Buffer* buf)
    {
      if(_recv_statu != RECV_HTTP_LINE) return false;
      ILOG("Recv HttpRequestLine .......");
      std::string line = buf->GetLineAndPop();
      if(line.size() == 0)
      {
        //不足一行的情况
        if(buf->ReadAbleSize() > MAX_LINE)
        {
          //当前行的长度超过8196
          _resp_staut = 414;
          _recv_statu = RECV_HTTP_ERROR;
          return false; 
        }
        return true; 
      }
      if(line.size() > MAX_LINE) 
      {
        _resp_staut = 414;
        _recv_statu = RECV_HTTP_ERROR;
        return false; 
      }
      _recv_statu = RECV_HTTP_HEAD; 
      return ParseHttpLine(line); 
    }
    bool RecvHttpHead(Buffer* buf)
    {
        if(_recv_statu != RECV_HTTP_HEAD ) return false;
        ILOG("Recv HttpRequestHead .......");
        while(1)
        {

          std::string line = buf->GetLineAndPop();
          if(line.size() == 0)
          {
            //不足一行的情况
            if(buf->ReadAbleSize() > MAX_LINE)
            {
              //当前行的长度超过8196
              _resp_staut = 414;
              _recv_statu = RECV_HTTP_ERROR;
              return false; 
            }
            return true; 
          }
          if(line.size() > MAX_LINE) 
          {
            _resp_staut = 414;
            _recv_statu = RECV_HTTP_ERROR;
            return false; 
          }
          if(line == "\n" || line == "\r\n") break;
          bool ret = ParseHttpHead(line);
          if(ret == false)return false;
       }
      _recv_statu = RECV_HTTP_BODY;
      return true;
   }
    bool RecvHttpBody(Buffer* buf)
    {
      if(_recv_statu != RECV_HTTP_BODY) return false; 
      ILOG("Recv HttpRequestBody .......");
      size_t content_length = _request.ContentLength(); 
      if(content_length == 0)
      {
        //正文没有数据
        _recv_statu = RECV_HTTP_OVER; 
        return true; 
      }
      size_t real_len = content_length - _request._body.size(); //实际还需要读取的大小
      if(buf->ReadAbleSize() >= real_len)
      {
        //这一次可以读完 
        _request._body.append(buf->ReadPosition(),real_len); 
        buf->MoveReadOffset(real_len);
        _recv_statu = RECV_HTTP_OVER;
        return true; 
      }

      //缓冲区数据没有读完正文 
      _request._body.append(buf->ReadPosition(),buf->ReadAbleSize());
      buf->MoveReadOffset(buf->ReadAbleSize());
      return true;
    }
    bool ParseHttpLine(std::string& line)
    {
        ILOG("Parse HttpRequestLine: %s",line.c_str());
        if(line.back() == '\n') line.pop_back();
        if(line.back() == '\r') line.pop_back();
        std::smatch matches; 
        //利用正则分割字符串
        std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?",std::regex::icase);
        std::string str;
        bool ret = std::regex_match(line,matches,e);
        if(ret == false)
        {
          ILOG("正则匹配失败");
          _recv_statu = RECV_HTTP_ERROR;
          _resp_staut = 400;
          return false; 
        }
        //0:GET /hellowold/login?user=xiaoming&pass=123123 HTTP/1.1
			  //1:GET
			  //2:/hellowold/login
			  //3:user=xiaoming&pass=123123
			  //4:HTTP/1.1
        _request._method = matches[1]; //获取请求方法
        std::transform(_request._method.begin(),_request._method.end(),_request._method.begin(),::toupper);
        _request._path = Util::UrlDcode(matches[2],true); //获取请求路径
        _request._version = matches[4]; //获取协议版本
        std::string query_string = matches[3]; //获取GET请求上传的数据
				std::vector<std::string> query_string_arr; 
				//把matches[3]用&分割
				Util::split(query_string,"&",&query_string_arr); 
				//遍历query_string_arr
				for(auto& str : query_string_arr)	
				{
	        //把str用=号分割成key value结构
          size_t pos = str.find("="); 
          if(pos == std::string::npos)
          {
            DLOG("=标识没有找到");
            _resp_staut = 400 ;
            _recv_statu = RECV_HTTP_ERROR;
            return false; 
          }
          //0 - pos 是key ， pos+1 - str.size()  value  
          std::string key = Util::UrlDcode(str.substr(0,pos),true); 
          std::string value = Util::UrlDcode(str.substr(pos+1),true);
          ILOG("Parse Line Success");
          _request.SetParam(key,value);
				}
				return true;	
    }
    bool ParseHttpHead(std::string& line)
    {
      ILOG("Parse HttpRequestHead: %s",line.c_str());
      if(line.back() == '\n') line.pop_back();
      if(line.back() == '\r') line.pop_back();
      size_t pos = line.find(": "); 
      if(pos == std::string::npos) 
      {
        DLOG(":分隔符没有找到");
        _resp_staut = 400; 
        _recv_statu = RECV_HTTP_ERROR; 
        return false;
      }
      std::string key = line.substr(0,pos); 
      std::string value = line.substr(pos+2);
      _request.SetHeader(key,value);
      return  true;
    }

  public:
    HttpContext():_resp_staut(200),_recv_statu(RECV_HTTP_LINE){}
    int GetRespStatu(){return _resp_staut;}
    HttpRecvStatu GetRecvStatu(){return _recv_statu;}
    HttpRequest& GetRequest() {return _request;;}
    void RecvHttpRequese(Buffer* buf)
    {
      //解析并接收请求
      switch(_recv_statu)
      {
      case RECV_HTTP_LINE: RecvHttpLine(buf);
      case RECV_HTTP_HEAD: RecvHttpHead(buf);
      case RECV_HTTP_BODY: RecvHttpBody(buf);
      }
    }
    void Reset()
    {
      _recv_statu = RECV_HTTP_LINE;
      _resp_staut = 200;
      _request.Reset();
    }
  };


  class HttpServer
  {
  private:
    using Handler = std::function<void(const HttpRequest&,HttpResponse*)>;
    using Handlers = std::vector<std::pair<std::regex,Handler>>;

    Handlers _get_route;
    Handlers _post_route;
    Handlers _put_route;
    Handlers _delete_route;
    std::string _basedir; //静态资源根目录
    TcpServer _tcp_server;
  
  private:
    void ErrorHandler(const HttpRequest& req,HttpResponse* resp)
    {
            DLOG("ERROR Handler");
            std::string body;
            body += "<html>";
            body += "<head>";
            body += "<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>";
            body += "</head>";
            body += "<body>";
            body += "<h1>";
            body += std::to_string(resp->_statu);
            body += " ";
            body += Util::StatuDesc(resp->_statu);
            body += "</h1>";
            body += "</body>";
            body += "</html>";
            resp->SetContext(body,"text/html");
    }
    //组织Respon并发送 
    void WriteResponse(const PtrConnection& conn ,const HttpRequest& req, HttpResponse& resp)
    {
        //1完善头部字段 
        if(req.Close() == true) 
        {
          resp.SetHeader("Connection","close"); //设置短链接 
        }else 
        {
          resp.SetHeader("Connection","keep-alive"); //设置长连接
        }

        if(resp._body.empty() == false && resp.HasHeader("Content-Length")) 
        {
          //如果没有设置正文长度，则设置正文长度 
          resp.SetHeader("Content-Length", std::to_string(req._body.size())); 
        }

        if(resp._body.empty() == false && resp.HasHeader("Content-Type"))
        {
          //如果没有设置类型,则设置 
          resp.SetHeader("Content-Type","application/octet-stream");
        }

        //是否设置重定向 
        if(resp._redirect_flag == true)
        {
          resp.SetHeader("Location",resp._redirect_url); 
        }

        //2.将rsp的要素按照http协议进行组织 
        std::string str;
        //http/1.0 200 ok  组织响应行
        str += req._version + " " + std::to_string(resp._statu) + " " + Util::StatuDesc(resp._statu) + "\n";
        //组织响应报头 
        for(auto& h : resp._headers)
        {
          str += h.first + ": " + h.second + "\n"; 
        }
        //组织空行 
        str += "\n"; 
        //组织正文 
        str += resp._body; 
        //3.发送数据 
        conn->Send(str.c_str(),str.size());
    }
    bool IsFileHandle(const HttpRequest& req) 
    {
      //1.根目录为空，绝对不是静态处理资源文件
      if(_basedir.empty()) return false;  
      //2.请求方法必须是GET或者HEAD
      DLOG("method:%s",req._method.c_str());
      if(req._method != "GET"  &&  req._method != "HEAD") return false; 

      //3.请求的资源必须是个合法路径 
      if(!Util::ValidPath(req._path)){ DLOG("NO VALIDPATH"); return false; }

      //4.请求资源必须存在且必须是一个普通文件
      std::string req_path = _basedir + req._path; 
      if(req_path.back() == '/')
      {
        if(req_path[req_path.size() - 2] == '/') req_path.pop_back();
        //是根目录，自动在末尾加上index.html 
        req_path += "index.html";
      }
      DLOG("req real path : %s",req_path.c_str());
      //判断目录是否是普通文件 
      if(!Util::IsRegular(req_path)){ DLOG("NO ISREGULAR"); return false; }
      return true; 

    }
    //处理静态资源请求
    bool FileHandler(const HttpRequest& req,HttpResponse* resp)
    {
        std::string req_path = _basedir + req._path; 
        if(req_path.back() == '/')
        {
          if(req_path[req_path.size() - 2] == '/') req_path.pop_back();
          //是根目录，自动在末尾加上index.html 
          req_path += "index.html";
        }
        bool ret =  Util::ReadFile(req_path,&resp->_body);  
        if(!ret) return false ;
        std::string mime = Util::ExtMine(req_path);  
        resp->SetHeader("Content-Type",mime);
        return true;
    }
    //功能性请求分类处理 
    void Dispatcher(HttpRequest& req,HttpResponse* resp,Handlers& handlers )
    {
      for(auto& h : handlers)
      {
        std::regex re = h.first;
        const Handler& functor = h.second; 
        bool ret = std::regex_match(req._path,req._matches,re); 
        if(!ret) continue; 
        functor(req,resp);
        return; 
      }
      DLOG("404.....");
      resp->_statu = 404;
    }
    void Route(HttpRequest& req, HttpResponse* resp)
    {
      //进行静态资源处理函数处理，如果处理成功返回true  
      if(IsFileHandle(req) == true)
      {
        //是静态资源请求 
        FileHandler(req,resp);
        return; 
      }
      //功能性请求 
      if(req._method == "GET" || req._method == "HEAD")
      {
        Dispatcher(req,resp,_get_route);
        return; 
      }else if(req._method == "POST")
      {
        Dispatcher(req,resp,_post_route);
        return; 
      }else if(req._method == "PUT")
      {
        Dispatcher(req,resp,_put_route);
        return; 
      }else if(req._method == "DELETE")
      {
        Dispatcher(req,resp,_delete_route);
        return;
      }

      //不属于上面五种请求方法，设置状态码405 
      resp->_statu = 405;
    }
    //设置上下文
    void SetContext(const PtrConnection& conn)
    { 
      conn->SetContext(HttpContext());
      DLOG("NEW CONNECTION : %p",conn.get());
    }
    //处理缓冲区数据，解析+处理
    void MessageHandler(const PtrConnection& conn , Buffer* buf)
    {
      while(buf->ReadAbleSize() > 0)
      {
         //1.获取上下文 
         DLOG("获取上下文");
         HttpContext* context = conn->GetContext()->get<HttpContext>();
         //2.解析并处理上下文
         DLOG("处理请求");
         context->RecvHttpRequese(buf); //解析上下文，并放在_request中 
        DLOG("上下文解析完成");
         HttpRequest& req = context->GetRequest();
         DLOG("获取请求完成");
         HttpResponse resp(context->GetRespStatu()); 
         if(context->GetRespStatu() >= 400)
         {
           //解析时发生错误 
           DLOG("解析发生错误");
           ErrorHandler(req,&resp);
           WriteResponse(conn,req,resp); 
           context->Reset(); 
           buf->MoveReadOffset(buf->ReadAbleSize()); //清空缓冲区
           conn->Shutdown(); 
           return;
         }
         if(context->GetRecvStatu() != RECV_HTTP_OVER) 
         {
           DLOG("请求没读完，正在继续读取,.....");
           //请求还没结束说明数据没有读取完 
           return;
         }
         //3.请求路由+业务处理 
         DLOG("请求路由+业务处理"); 
         Route(req,&resp);
         //4.组织响应并发送
         DLOG("组织响应并发送");
         WriteResponse(conn,req,resp); 
         //5.重置上下文 
         context->Reset();
         //6.根据长短连接判断是否关闭连接或者继续处理 
         if(resp.Close()) conn->Shutdown();
     }
    }
  public:
    HttpServer(int port , int timeout = DEFAULT_TIMEOUT) : _tcp_server(port) 
    {
      _tcp_server.EnableInactiveRelease(timeout);
      _tcp_server.SetConnectedCallBack(std::bind(&HttpServer::SetContext,this,std::placeholders::_1));
      _tcp_server.SetMessageCallBack(std::bind(&HttpServer::MessageHandler,this,std::placeholders::_1,std::placeholders::_2));
    }
    //设置静态根目录 
    void SetBaseDir(const std::string& path)
    {
      assert(Util::IsDirectory(path));
      _basedir = path;
    }
    void AddGet(const std::string& pattern,const Handler& handler)
    {
      _get_route.push_back(std::make_pair(std::regex(pattern),handler));
    }
    void AddPost(const std::string& pattern,const Handler& handler)
    {
      _post_route.push_back(std::make_pair(std::regex(pattern),handler));
    }
    void AddPut(const std::string& pattern,const Handler& handler)
    {
      _put_route.push_back(std::make_pair(std::regex(pattern),handler));

    }
    void AddDelete(const std::string& pattern,const Handler& handler)
    {
      _delete_route.push_back(std::make_pair(std::regex(pattern),handler));
    }
    void SetThreadCount(int count)
    {
      _tcp_server.SetThreadCount(count);
    }
    void Listen()
    {
      _tcp_server.Start();
    }
  };

}





